


from martingale.martingale import pd
import os


dirPd = pd.__path__[0]


SIMULATE = False
EXT_ROOT = 'Root'
EXT_ROOT_PD_TEST = 'Root.test.pd'
EXT_ROOT_PD = 'Root.pd'
EXT_PD_TEST = '.test.pd'
EXT_PD = '.pd'


class Platform(object):

    def __init__(self, dirPd):
        self.dirPd = dirPd
        self.dirMartingale = os.path.dirname(dirPd)
        self.dirCompositions = os.path.join(self.dirMartingale, 'compositions')
        self.dirLib = os.path.join(self.dirPd, 'lib')
        self.dirInstruments = os.path.join(self.dirPd, 'instruments')

        self.dirRoot = 'dualAnalogRoot'
        self.dirTargetInstruments = None # defined in subclasses 
        self.modNameAppend = 'ERROR.pd' # define in subclass

        self.targetCompositions = [
            {'path':['arizaWork02', 'arizaWork02-performanceRoot.pd'],
             'replacements':['mgHwDualAnalogPoly6'] },
            {'path':['arizaWork02', 'arizaWork02-performanceRoot.test.pd'],
             'replacements':['arizaWork02-performanceRoot'] },

            {'path':['arizaWork03', 'arizaWork03-performanceRoot.pd'],
             'replacements':['mgHwDualAnalogPoly8'] }, # 8 here
            {'path':['arizaWork03', 'arizaWork03-performanceRoot.test.pd'],
             'replacements':['arizaWork03-performanceRoot'] },
        ]


        self.targetInstruments = [
            # mono instruments
            {'path':['mono', 'performance-a.pd'],
             'replacements':['mgHwDualAnalogPoly1'] },
            {'path':['mono', 'performance-a.test.pd'],
             'replacements':[] },

            {'path':['mono', 'performance-b.pd'],
             'replacements':['mgHwDualAnalogPoly1'] },
            {'path':['mono', 'performance-b.test.pd'],
             'replacements':[] },

            # poly instruments
            {'path':['poly', 'performance-a.pd'],
             'replacements':['mgHwDualAnalogPoly2'] },
            {'path':['poly', 'performance-a.test.pd'],
             'replacements':[] },

            {'path':['poly', 'performance-b.pd'],
             'replacements':['mgHwDualAnalogPoly2'] },
            {'path':['poly', 'performance-b.test.pd'],
             'replacements':[] },

            {'path':['poly', 'performance-c.pd'],
             'replacements':['mgHwDualAnalogPoly3'] },
            {'path':['poly', 'performance-c.test.pd'],
             'replacements':[] },
            {'path':['poly', 'performance-c.pdf'],
             'replacements':[] },

            {'path':['poly', 'performance-d.pd'],
             'replacements':['mgHwDualAnalogPoly6'] },
            {'path':['poly', 'performance-d.test.pd'],
             'replacements':[] },
#             {'path':['poly', 'performance-d.pdf'],
#              'replacements':[] },
            {'path':['poly', 'performance-dParameters.pd'],
             'replacements':[] },
        ]

        self.targetLibrary = [
            # declare target file, and components with that need to be replaced with platform specific files 
            {'path':['mgHwDualAnalogPoly1.pd'], 
             'replacements':['mgHwDualAnalog'] }, 
            {'path':['mgHwDualAnalogPoly1.test.pd'],
             'replacements':['mgHwDualAnalogPoly1'] },

            {'path':['mgHwDualAnalogPoly2.pd'], 
             'replacements':['mgHwDualAnalog'] }, 
            {'path':['mgHwDualAnalogPoly2.test.pd'],
             'replacements':['mgHwDualAnalogPoly2'] },

            {'path':['mgHwDualAnalogPoly3.pd'], 
             'replacements':['mgHwDualAnalog'] }, 
            {'path':['mgHwDualAnalogPoly3.test.pd'],
             'replacements':['mgHwDualAnalogPoly3'] },

            {'path':['mgHwDualAnalogPoly6.pd'], 
             'replacements':['mgHwDualAnalog'] }, 
            {'path':['mgHwDualAnalogPoly6.test.pd'],
             'replacements':['mgHwDualAnalogPoly6'] },

            {'path':['mgHwDualAnalogPoly8.pd'], 
             'replacements':['mgHwDualAnalog'] }, 
            {'path':['mgHwDualAnalogPoly8.test.pd'],
             'replacements':['mgHwDualAnalogPoly8'] },

        ]


    def _createFile(self, fp, content):
        tag = '''\n#X text 0 200 WARNING: this file is automatically generated with martingale/py/makePlatforms.py // do not edit!;'''
        
        # add tag: this does not yet work
        #content += tag
        f = open(fp, 'w')
        f.write(content)
        f.close()

    def replace(self, src):
        if src == 'mgHwDualAnalog':
            return 'mgHwDualAnalog' + self.modNameAppend
        elif src == 'mgHwDualAnalogPoly1':
            return 'mgHwDualAnalogPoly1' + self.modNameAppend
        elif src == 'mgHwDualAnalogPoly2':
            return 'mgHwDualAnalogPoly2' + self.modNameAppend
        elif src == 'mgHwDualAnalogPoly3':
            return 'mgHwDualAnalogPoly3' + self.modNameAppend
        elif src == 'mgHwDualAnalogPoly4':
            return 'mgHwDualAnalogPoly4' + self.modNameAppend
        elif src == 'mgHwDualAnalogPoly5':
            return 'mgHwDualAnalogPoly5' + self.modNameAppend
        elif src == 'mgHwDualAnalogPoly6':
            return 'mgHwDualAnalogPoly6' + self.modNameAppend
        elif src == 'mgHwDualAnalogPoly7':
            return 'mgHwDualAnalogPoly7' + self.modNameAppend
        elif src == 'mgHwDualAnalogPoly8':
            return 'mgHwDualAnalogPoly8' + self.modNameAppend

        # dynamic replacements based on conventions used in compositions
        # test files
        elif src.endswith(EXT_ROOT):
            return src.replace(EXT_ROOT, self.modNameAppend)

        else:
            raise Exception('no replacement for: %s' % src)


    def updateCompositions(self):
        '''Here, writing in the same directory, but need to change file name.
        '''
        for t in self.targetCompositions:
            srcPath = [self.dirCompositions]
            for sub in t['path']:
                srcPath.append(sub)
            src = os.path.join(*srcPath)
            if not os.path.exists(src):
                raise Exception('no such path: %s' % src)
            print 'src', src

            dstPath = [self.dirCompositions]
            for sub in t['path']:
                dstPath.append(sub)
            # modify last part of file nam
            dst = os.path.join(*dstPath)
            if dst.endswith(EXT_ROOT_PD_TEST):
                dst = dst.replace(EXT_ROOT_PD_TEST, 
                    self.modNameAppend + EXT_PD_TEST)
            elif dst.endswith(EXT_ROOT_PD):
                dst = dst.replace(EXT_ROOT_PD, self.modNameAppend + EXT_PD)
            else:
                raise Exception('dst file does not end with .pd or .test.pd')
            print 'dst', dst

            f = open(src, 'r')
            content = f.read()
            f.close()        
            for replaceSrc in t['replacements']:
                replaceDst = self.replace(replaceSrc)
                print 'replacing %s with %s' % (replaceSrc, replaceDst)
                content = content.replace(replaceSrc, replaceDst)
            # always write destination, even if not doing replacement   

            if not SIMULATE:
                self._createFile(dst, content)    


    def updateInstruments(self):
        for t in self.targetInstruments:
            srcPath = [self.dirInstruments, self.dirRoot]
            for sub in t['path']:
                srcPath.append(sub)
            src = os.path.join(*srcPath)
            if not os.path.exists(src):
                raise Exception('no such path: %s' % src)
            print 'src', src

            dstPath = [self.dirInstruments, self.dirTargetInstruments]
            for sub in t['path']:
                dstPath.append(sub)
            dst = os.path.join(*dstPath)
            print 'dst', dst

            f = open(src, 'r')
            content = f.read()
            f.close()        
            for replaceSrc in t['replacements']:
                replaceDst = self.replace(replaceSrc)
                print 'replacing %s with %s' % (replaceSrc, replaceDst)
                content = content.replace(replaceSrc, replaceDst)
            # always write destination, even if not doing replacement   

            if not SIMULATE:
                self._createFile(dst, content)    

    def updateLibrary(self):
        for t in self.targetLibrary:
            srcPath = [self.dirLib]
            for sub in t['path']:
                srcPath.append(sub)
            src = os.path.join(*srcPath)
            if not os.path.exists(src):
                raise Exception('no such path: %s' % src)
            print 'src', src

            # need to create new file name for the new library entity:
            # this is different than for instruments
            dstPath = [self.dirLib]
            for sub in t['path']:
                dstPath.append(sub)
            dst = os.path.join(*dstPath)
            # replace.py with new file name components
            if dst.endswith(EXT_PD_TEST):
                dst = dst.replace(EXT_PD_TEST, self.modNameAppend + EXT_PD_TEST)
            elif dst.endswith(EXT_PD):
                dst = dst.replace(EXT_PD, self.modNameAppend + EXT_PD)
            else:
                raise Exception('dst file does not end with .pd or .test.pd')
            print 'dst', dst

            f = open(src, 'r')
            content = f.read()
            f.close()        
            for replaceSrc in t['replacements']:
                replaceDst = self.replace(replaceSrc)
                print 'replacing %s with %s' % (replaceSrc, replaceDst)
                content = content.replace(replaceSrc, replaceDst)
            # always write destination, even if not doing replacement   

            if not SIMULATE:
                self._createFile(dst, content)    



class ChillStream(Platform):
    def __init__(self, dirPd):
        Platform.__init__(self, dirPd)
        self.dirTargetInstruments = 'dualAnalogChillStream'
        # replace .pd with this in the newly generated file
        self.modNameAppend = 'ChillStream'

class Sixaxis(Platform):
    def __init__(self, dirPd):
        Platform.__init__(self, dirPd)
        self.dirTargetInstruments = 'dualAnalogSixaxis'
        # replace .pd with this in the newly generated file
        self.modNameAppend = 'Sixaxis'

class Joystick(Platform):
    def __init__(self, dirPd):
        Platform.__init__(self, dirPd)
        self.dirTargetInstruments = 'dualAnalogJoystick'
        # replace .pd with this in the newly generated file
        self.modNameAppend = 'Joystick'

class Virtual(Platform):
    def __init__(self, dirPd):
        Platform.__init__(self, dirPd)
        self.dirTargetInstruments = 'dualAnalogVirtual'
        # replace .pd with this in the newly generated file
        self.modNameAppend = 'Virtual'


if __name__ == '__main__':

    platforms = [ChillStream(dirPd), Sixaxis(dirPd), Joystick(dirPd), Virtual(dirPd),]

    for p in platforms:
        print 
        print p

        print 'updating instruments:'
        p.updateInstruments()
        print 'updating library:'
        p.updateLibrary()

        print 'updating compositions:'
        p.updateCompositions()